package com.anda.driver.locator.service;

import java.util.Calendar;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;

import com.anda.driver.locator.LocationInfo;
import com.anda.driver.util.Constant;
import com.anda.driver.util.DBHelper;
import com.anda.driver.util.TelephonyUtil;
import com.anda.driver.util.UploadLocation;

public class LocatorService extends Service {
	private Handler handler;
	private LocationListener locationListener;
	private LocationManager locationManager;
	private String locationProvider = LocationManager.GPS_PROVIDER;
	private PowerManager.WakeLock wakeLock;
	@Override
	public IBinder onBind(Intent paramIntent) {
		return null;
	}
	@Override
	public void onCreate() {
		super.onCreate();		
		wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE))
				.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DoNotDimScreen");
		wakeLock.acquire();
		
		locationManager = ((LocationManager) getSystemService(Context.LOCATION_SERVICE));		
		locationListener = new LocationListener() {
			public void onLocationChanged(Location location) {
				Constant.debug("---------------get location from gps---------" + location);
				new GpsLocationGetTask().executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR,location);
			}

			public void onProviderDisabled(String paramString) {
			}
			public void onProviderEnabled(String paramString) {
			}
			public void onStatusChanged(String paramString, int paramInt,
					Bundle paramBundle) {
			}
		};
		handler = new Handler();
		handler.post(new CellThread());
		handler.post(new GpsThread());
		
		Constant.debug("-----LocatorService create.-------");
	}

	public void onDestroy() {
		super.onDestroy();
		try {
			this.locationManager.removeUpdates(this.locationListener);
		} catch (Exception e){
			e.printStackTrace();
		}
		if (wakeLock != null && wakeLock.isHeld()) {
			wakeLock.release();
		}
		Constant.debug("----------LocatorService destroy.----------");
	}

	public int onStartCommand(Intent paramIntent, int paramInt1, int paramInt2) {
		Constant.debug("LocatorService startCommand.");
		return 1;
	}


	class CellThread implements Runnable {
		public void run() {
			Constant.debug("---------------begin to get location from cell---------");
			new CellLocationGetTask().executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR,LocatorService.this);
		}
	}
	class GpsThread implements Runnable {
		public void run() {
			long lastTime = DBHelper.getLastGpsTime(LocatorService.this,null);
			if (Calendar.getInstance().getTimeInMillis() - lastTime < Constant.gpsMinTime) 
			{
				LocatorService.this.handler.postDelayed(new GpsThread(),
					Constant.gpsMinTime - (Calendar.getInstance().getTimeInMillis() - lastTime)
				);
				return ;
			}
			Constant.debug("---------------begin to get location from gps---------");
			LocatorService.this.locationManager.requestLocationUpdates(LocatorService.this.locationProvider,
					Constant.gpsMinTime, 0.0F, LocatorService.this.locationListener);
		}
	}
	
	class CellLocationGetTask extends AsyncTask<Context, Void, Long> {

		@Override
		protected Long doInBackground(Context... context) {			
			long lastTime = DBHelper.getLastGpsTime(LocatorService.this,null);
			long now = Calendar.getInstance().getTimeInMillis();
			if (now - lastTime < Constant.cellMinTime) 
			{
				Constant.debug(new StringBuffer().append("--------cellTime: ").append(now).append(" - ").append(lastTime).append(" = ").append(now - lastTime).append(" < ").append(Constant.cellMinTime).toString());
				return Constant.cellMinTime - (now - lastTime);
			}
			
			LocationInfo locationInfo = TelephonyUtil
					.getLocationInfo(LocatorService.this);
			Constant.debug("---------------get location from cell---------" + locationInfo);
			if (locationInfo != null) {
				long id = DBHelper.insertLoc(LocatorService.this, locationInfo);
				locationInfo.setId((int) id);
				new UploadLocation(LocatorService.this)
					.executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR,new LocationInfo[] { locationInfo });
			} 
			return Constant.cellMinTime;
		}

		@Override
		protected void onPostExecute(Long l) {
			Constant.debug("---------------get location from cell after ---------" + l + "("+l/1000/60+")");
			LocatorService.this.handler.postDelayed(new CellThread(),l);
		}
		
	}
	
	class GpsLocationGetTask extends AsyncTask<Location , Void, Long>{

		@Override
		protected Long doInBackground(Location... locations) {
			Location location = locations[0];
			if (location != null) {
				
				
				LocationInfo[] locs = new LocationInfo[1];
				locs[0] = new LocationInfo("gps");
				locs[0].setAccuracy(location.getAccuracy());
				locs[0].setLat(location.getLatitude());
				locs[0].setLng(location.getLongitude());
				locs[0].setGetTime(Calendar.getInstance().getTimeInMillis());

				LocationInfo li = TelephonyUtil
						.getLocationByLatLng(location);
				if (li != null) {
					locs[0].setAccessToken(li.getAccessToken());
					locs[0].setCity(li.getCity());
					locs[0].setCountry(li.getCountry());
					locs[0].setCountryCode(li.getCountryCode());
					locs[0].setRegion(li.getRegion());
					locs[0].setStreet(li.getStreet());
					locs[0].setStreetNumber(li.getStreetNumber());
				}

				long id = DBHelper.insertLoc(LocatorService.this, locs[0]);
				locs[0].setId((int) id);
				new UploadLocation(LocatorService.this).executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR,locs);
			}
			return Constant.gpsMinTime;
		}
		
		@Override
		protected void onPostExecute(Long l) {
			locationManager.removeUpdates(locationListener);
			Constant.debug("---------------get location from gps after ---------" + l + "("+l/1000/60+")");
			LocatorService.this.handler.postDelayed(new GpsThread(),l);
		}
	}
	
}